﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using AccelerateSensor.Console.Tools;

namespace AccelerateSensor.Console
{
    public class SocketServer : ISocketMsgHandlerObserver
    {
        #region Thread
        private Thread _threadWorker;
        private bool _threadWorking;
        private readonly object _threadWorkingLockHelper = new object();

        private bool IsThreadWorking
        {
            get
            {
                bool ret;
                lock (_threadWorkingLockHelper)
                {
                    ret = _threadWorking;
                }

                return ret;
            }
            set
            {
                lock (_threadWorkingLockHelper)
                {
                    _threadWorking = value;
                }
            }
        } 
        #endregion

        private readonly Socket _socket;
        private readonly SocketMsgHandler _socketMsgHandler;
        private readonly SendMsgHelper _sendMsgHelper;
        private readonly int Timeout = 10000;

        public SocketServer()
        {
            //创建Socket
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //创建消息处理类
            _socketMsgHandler = new SocketMsgHandler(this);

            _sendMsgHelper = new SendMsgHelper();
        }

        private bool InitSocket(int port)
        {
            try
            {
                //设置Socket
                _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                var host = "192.168.36.111";
                var ipAddress = IPAddress.Parse(host);
                var ipEndPoint = new IPEndPoint(ipAddress, port);
                _socket.Bind(ipEndPoint);
                _socket.Listen(5);

                return true;
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                return false;
            }
        }

        public bool Start(int port)
        {
            if (!InitSocket(port))
            {
                return false;
            }

            _socketMsgHandler.Start();

            IsThreadWorking = true;
            _threadWorker = new Thread(ThreadFunc) { IsBackground = true };
            _threadWorker.Start();

            return true;
        }

        public void Stop()
        {
            IsThreadWorking = false;

            try
            {
                _socket.Close(10);
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
            }

            _threadWorker?.Join();
            _threadWorker = null;

            _socketMsgHandler.Stop();
        }

        private void ThreadFunc(object state)
        {
            var buffer = new byte[1024 * 1024]; //1MB缓存

            Socket client;

            try
            {
                client = _socket.Accept();
                client.SetSocketOption(SocketOptionLevel.Socket,
                    SocketOptionName.ReceiveTimeout, /*Timeout*/1000 * 120);
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                return;
            }

            while (IsThreadWorking)
            {
                try
                {
                    if (!ReceiveData(client, buffer))
                    {
                        break;
                    }

                    Thread.Sleep(2);
                }
                catch (Exception e)
                {
                    LogHelper.AddErrorLog($"ThreadFunc Exception: {e.Message}.");
                    System.Console.WriteLine(e);
                    break;
                }
            }

            IsThreadWorking = false;
        }

        private bool ReceiveData(Socket client, byte[] buffer)
        {
            var dataNum = client.Receive(buffer, 4, SocketFlags.None);
            if (dataNum == 0)
            {
                System.Console.WriteLine("客户端断开连接");
                return false;
            }

            if (dataNum != 4)
            {
                return true;
            }

            var lenBuffer = new byte[4];
            Buffer.BlockCopy(buffer, 0, lenBuffer, 0, 4);
            Array.Reverse(lenBuffer, 0, 4); //将大端码转换为小端码
            var dataLen = BitConverter.ToInt32(lenBuffer, 0);
            if (dataLen <= 0)
            {
                return true;
            }

            System.Console.WriteLine($"len = {dataLen}");
            LogHelper.AddLog($"len = {dataLen}");

            dataNum = client.Receive(buffer, dataLen, SocketFlags.None);
            if (dataNum == 0)
            {
                System.Console.WriteLine("客户端断开连接");
                return false;
            }

            if (dataNum != dataLen)
            {
                //获取数据不对
                return true;
            }

            var message = Encoding.UTF8.GetString(buffer, 0, dataLen);
            LogHelper.AddLog($"Receive msg:{Environment.NewLine}{message}");

            _socketMsgHandler.AddMessage(message);
            return true;
        }

        public void ReceiveHeartbeat()
        {
            _sendMsgHelper.SendHeartbeat(_socket);
        }
    }
}
